package lab.exec;

import cn.flant.log.Logger;

public class ExecuteThread<T> implements Runnable, Comparable<ExecuteThread<T>> {
	private static int executeThreadCount = 0;
	private Logger log = Logger.getLogger(ExecuteThread.class);
	private ProcessQueueGroup<T> queueGroup = new ProcessQueueGroup<T>();
	private Processor processor = null;
	private String name = getClass().getSimpleName() + "-" + (++executeThreadCount);
	private Thread runner = null;
	private boolean isRunning = false;

	public ExecuteThread(Processor processor) {
		this.processor = processor;
	}

	public void run() {
		while (isRunning) {
			T obj = null;
			while (isRunning && (obj = queueGroup.pollObject()) != null) {
				try {
					processor.process(obj);
				} catch (Throwable e) {
					log.error("", e);
				}
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
		}
	}

	public synchronized void startup() {
		if (isRunning) {
			return;
		}
		isRunning = true;
		runner = new Thread(this, name);
		runner.start();
	}

	public synchronized void shutdown() {
		if (!isRunning) {
			return;
		}
		isRunning = false;
		if (runner != null) {
			runner.interrupt();
			try {
				runner.join();
			} catch (InterruptedException e) {
			}
			runner = null;
		}
	}

	public void addProcessQueue(ProcessQueue<T> queue) {
		queueGroup.addProcessQueue(queue);
	}

	public boolean removeProcessQueue(ProcessQueue<T> queue) {
		return queueGroup.removeProcessQueue(queue);
	}

	public void clearProcessQueue() {
		queueGroup.clearProcessQueue();
	}

	public Processor getProcessor() {
		return processor;
	}

	public void setProcessor(Processor processor) {
		this.processor = processor;
	}

	public int getQueueSize() {
		return queueGroup.getSize();
	}

	public int getQueueCount() {
		return queueGroup.getQueueCount();
	}

	public int compareTo(ExecuteThread<T> o) {
		return queueGroup.getSize() - o.getQueueSize();
	}

	public String toString() {
		return name;
	}
}
